﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Forms;
using DevExpress.XtraBars.Docking2010;
using DevExpress.XtraBars.Docking2010.Views;
using Loki.Utils;

namespace Loki.UI.Win
{
    public class DocumentBinder : Binder
    {
        public void Bind<TModel>(DocumentManager manager, Expression<Func<TModel, object>> propertyGetter) where TModel : class
        {
            manager.ShowThumbnailsInTaskBar = DevExpress.Utils.DefaultBoolean.False;

            var containerModel = GetContainer<TModel>(manager.ContainerControl, propertyGetter);
            if (containerModel == null)
            {
                return;
            }

            AddDocument(manager, containerModel.Children);

            containerModel.Children.CollectionChanged += (s, e) =>
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        AddDocument(manager, e.NewItems);
                        break;

                    case NotifyCollectionChangedAction.Remove:
                        RemoveDocument(manager, e.OldItems);
                        break;

                    case NotifyCollectionChangedAction.Replace:
                        e.NewItems.OfType<IChild>().Apply(x => x.Parent = this);
                        e.OldItems.OfType<IChild>().Apply(x => x.Parent = null);
                        break;

                    case NotifyCollectionChangedAction.Reset:
                        ResetDocuments(manager, containerModel.Children);
                        break;
                }
            };
        }

        private void AddDocument(DocumentManager manager, IEnumerable newModels)
        {
            foreach (var documentModel in newModels)
            {
                CreateDocument(manager, documentModel);
            }
        }

        private BaseDocument CreateDocument(DocumentManager manager, object model)
        {
            var template = UIContext.Templates.GetTemplate(model) as Control;
            if (template == null)
            {
                template = new Control();
            }

            template.Tag = model;
            var document = manager.View.AddDocument(template);

            document.Caption = GetName(model);
            document.Header = GetName(model);

            IActivable activableModel = model as IActivable;
            if (activableModel != null)
            {
                if (activableModel.IsActive)
                {
                    manager.View.ActivateDocument(document.Control);
                }

                activableModel.Activated += (s, e) => { manager.View.ActivateDocument(document.Control); };
            }

            Log.DebugFormat("Creating document for {0} naming {1}", model, GetName(model));

            return document;
        }

        private void RemoveDocument(DocumentManager manager, IEnumerable oldModels)
        {
            foreach (var documentModel in oldModels)
            {
                ViewModelExtenstions.TryDeactivate(documentModel, true);
                var oldDoc = manager.View.Documents.FindFirst(x => x.Control.Tag == documentModel);
                if (oldDoc != null)
                {
                    manager.View.Documents.Remove(oldDoc);
                }
            }
        }

        private void ResetDocuments(DocumentManager manager, IEnumerable listModels)
        {
            foreach (var document in manager.View.Documents)
            {
                ViewModelExtenstions.TryDeactivate(document.Control.Tag, true);
            }

            manager.View.Controller.CloseAll();

            AddDocument(manager, listModels);
        }
    }
}